package com.fish.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.crypto.digest.BCrypt;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fish.common.exception.BusinessException;
import com.fish.common.listener.ExcelImportListener;
import com.fish.common.result.ImportResult;
import com.fish.common.result.ResultCode;
import com.fish.common.util.ExcelUtil;
import com.fish.common.util.JwtUtil;
import com.fish.dao.mapper.UserMapper;
import com.fish.model.dto.*;
import com.fish.model.entity.Role;
import com.fish.model.entity.User;
import com.fish.model.entity.UserRole;
import com.fish.model.vo.*;
import com.fish.service.MenuService;
import com.fish.service.RoleService;
import com.fish.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import jakarta.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 用户服务实现类
 */
@Slf4j
@Service
public class UserServiceImpl implements UserService {
    
    @Autowired
    private UserMapper userMapper;
    
    @Autowired
    private RoleService roleService;
    
    @Autowired
    private ApplicationContext applicationContext;
    
    @Autowired
    private MenuService menuService;
    
    @Autowired
    private com.fish.dao.mapper.UserRoleMapper userRoleMapper;
    
    @Autowired
    private com.fish.dao.mapper.RoleMapper roleMapper;
    
    @Autowired
    private com.fish.service.TokenService tokenService;
    
    @Autowired
    private com.fish.common.service.CaptchaService captchaService;
    
    @Override
    public UserVO register(UserRegisterDTO registerDTO) {
        // 1. 验证图形验证码
        if (registerDTO.getCaptchaKey() != null && registerDTO.getCaptchaCode() != null) {
            if (!captchaService.verifyCaptcha(registerDTO.getCaptchaKey(), registerDTO.getCaptchaCode())) {
                throw new BusinessException(ResultCode.PARAM_ERROR.getCode(), "验证码错误或已过期");
            }
        }
        
        // 2. 参数校验
        if (!registerDTO.getPassword().equals(registerDTO.getConfirmPassword())) {
            throw new BusinessException(ResultCode.PARAM_ERROR.getCode(), "两次密码输入不一致");
        }
        
        // 3. 检查用户名是否已存在
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getUsername, registerDTO.getUsername());
        User existUser = userMapper.selectOne(queryWrapper);
        if (existUser != null) {
            throw new BusinessException(ResultCode.USER_EXIST);
        }
        
        // 4. 检查邮箱是否已被使用（如果提供了邮箱）
        if (StringUtils.hasText(registerDTO.getEmail())) {
            LambdaQueryWrapper<User> emailWrapper = new LambdaQueryWrapper<>();
            emailWrapper.eq(User::getEmail, registerDTO.getEmail());
            User emailUser = userMapper.selectOne(emailWrapper);
            if (emailUser != null) {
                throw new BusinessException(ResultCode.PARAM_ERROR.getCode(), "邮箱已被使用");
            }
        }
        
        // 5. 检查手机号是否已被使用（如果提供了手机号）
        if (StringUtils.hasText(registerDTO.getPhone())) {
            LambdaQueryWrapper<User> phoneWrapper = new LambdaQueryWrapper<>();
            phoneWrapper.eq(User::getPhone, registerDTO.getPhone());
            User phoneUser = userMapper.selectOne(phoneWrapper);
            if (phoneUser != null) {
                throw new BusinessException(ResultCode.PARAM_ERROR.getCode(), "手机号已被使用");
            }
        }
        
        // 6. 创建用户对象
        User user = new User();
        user.setUsername(registerDTO.getUsername());
        // 使用BCrypt加密密码
        user.setPassword(BCrypt.hashpw(registerDTO.getPassword()));
        user.setNickname(StringUtils.hasText(registerDTO.getNickname()) ? 
                registerDTO.getNickname() : registerDTO.getUsername());
        user.setEmail(registerDTO.getEmail());
        user.setPhone(registerDTO.getPhone());
        user.setStatus(1); // 默认状态为正常
        
        // 7. 保存到数据库
        int result = userMapper.insert(user);
        if (result <= 0) {
            throw new BusinessException("注册失败，请稍后重试");
        }
        
        // 8. 自动为新用户分配普通用户角色
        try {
            // 查询普通用户角色（role_key = 'user'）
            LambdaQueryWrapper<com.fish.model.entity.Role> roleWrapper = new LambdaQueryWrapper<>();
            roleWrapper.eq(com.fish.model.entity.Role::getRoleKey, "user");
            com.fish.model.entity.Role userRole = roleMapper.selectOne(roleWrapper);
            
            if (userRole != null) {
                // 创建用户角色关联
                com.fish.model.entity.UserRole userRoleEntity = new com.fish.model.entity.UserRole();
                userRoleEntity.setUserId(user.getId());
                userRoleEntity.setRoleId(userRole.getId());
                userRoleMapper.insert(userRoleEntity);
                log.info("为新用户[{}]自动分配普通用户角色", user.getUsername());
            } else {
                log.warn("未找到普通用户角色（role_key='user'），无法自动分配角色");
            }
        } catch (Exception e) {
            log.error("为新用户分配角色失败：", e);
            // 不抛出异常，允许用户注册成功，后续可由管理员手动分配角色
        }
        
        // 9. 返回用户信息（不包含密码）
        log.info("用户注册成功，用户名：{}", user.getUsername());
        return convertToUserVO(user);
    }
    
    @Override
    public LoginVO login(UserLoginDTO loginDTO) {
        // 1. 验证图形验证码
        if (loginDTO.getCaptchaKey() != null && loginDTO.getCaptchaCode() != null) {
            if (!captchaService.verifyCaptcha(loginDTO.getCaptchaKey(), loginDTO.getCaptchaCode())) {
                throw new BusinessException(ResultCode.PARAM_ERROR.getCode(), "验证码错误或已过期");
            }
        }
        
        // 2. 根据用户名、邮箱或手机号查询用户
        String account = loginDTO.getUsername();
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.and(wrapper -> wrapper
                .eq(User::getUsername, account)
                .or()
                .eq(User::getEmail, account)
                .or()
                .eq(User::getPhone, account)
        );
        User user = userMapper.selectOne(queryWrapper);
        
        log.info("登录账号：{}，查询到用户：{}", account, user != null ? user.getUsername() : "未找到");
        
        // 3. 检查用户是否存在
        if (user == null) {
            throw new BusinessException(ResultCode.USER_NOT_EXIST);
        }
        
        // 4. 验证密码
        if (!BCrypt.checkpw(loginDTO.getPassword(), user.getPassword())) {
            throw new BusinessException(ResultCode.PASSWORD_ERROR);
        }
        
        // 5. 检查用户状态
        if (user.getStatus() == 0) {
            throw new BusinessException(ResultCode.USER_DISABLED);
        }
        
        // 6. 生成双Token
        String accessToken = JwtUtil.generateAccessToken(user.getId(), user.getUsername());
        String refreshToken = JwtUtil.generateRefreshToken(user.getId(), user.getUsername());
        
        // 7. 保存Refresh Token
        tokenService.saveRefreshToken(user.getId(), refreshToken);
        
        // 8. 返回登录结果
        UserVO userVO = convertToUserVO(user);
        LoginVO loginVO = new LoginVO(accessToken, refreshToken, userVO);
        
        log.info("用户登录成功，用户名：{}", user.getUsername());
        return loginVO;
    }
    
    @Override
    public UserVO getUserById(Long userId) {
        User user = userMapper.selectById(userId);
        if (user == null) {
            throw new BusinessException(ResultCode.USER_NOT_EXIST);
        }
        return convertToUserVO(user);
    }
    
    @Override
    public UserVO getUserByUsername(String username) {
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getUsername, username);
        User user = userMapper.selectOne(queryWrapper);
        if (user == null) {
            throw new BusinessException(ResultCode.USER_NOT_EXIST);
        }
        return convertToUserVO(user);
    }
    
    @Override
    public UserInfoVO getUserInfoWithPermissions(Long userId) {
        // 1. 获取用户基本信息
        UserVO userVO = getUserById(userId);
        
        // 2. 获取用户角色
        List<Role> roles = roleService.getRolesByUserId(userId);
        List<RoleVO> roleVOS = roles.stream().map(role -> {
            RoleVO roleVO = new RoleVO();
            BeanUtil.copyProperties(role, roleVO);
            return roleVO;
        }).collect(Collectors.toList());
        
        // 3. 获取用户权限标识
        Set<String> permissions = menuService.getPermissionsByUserId(userId);
        
        // 4. 获取用户菜单树
        List<MenuVO> menus = menuService.getMenuTreeByUserId(userId);
        
        // 5. 组装返回数据
        UserInfoVO userInfoVO = new UserInfoVO();
        userInfoVO.setUserInfo(userVO);
        userInfoVO.setRoles(roleVOS);
        userInfoVO.setPermissions(permissions);
        userInfoVO.setMenus(menus);
        
        return userInfoVO;
    }
    
    @Override
    public Page<UserVO> getUserList(Long current, Long size, String username) {
        Page<User> page = new Page<>(current, size);
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        
        // 如果提供了用户名，进行模糊查询
        if (StringUtils.hasText(username)) {
            wrapper.like(User::getUsername, username);
        }
        
        wrapper.orderByDesc(User::getCreateTime);
        
        Page<User> userPage = userMapper.selectPage(page, wrapper);
        
        // 转换为VO
        Page<UserVO> voPage = new Page<>(userPage.getCurrent(), userPage.getSize(), userPage.getTotal());
        List<UserVO> userVOList = userPage.getRecords().stream()
                .map(this::convertToUserVO)
                .collect(Collectors.toList());
        voPage.setRecords(userVOList);
        
        return voPage;
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public UserVO addUser(UserAddDTO addDTO) {
        // 1. 检查用户名是否已存在
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getUsername, addDTO.getUsername());
        User existUser = userMapper.selectOne(queryWrapper);
        if (existUser != null) {
            throw new BusinessException(ResultCode.USER_EXIST);
        }
        
        // 2. 检查邮箱是否已被使用
        if (StringUtils.hasText(addDTO.getEmail())) {
            LambdaQueryWrapper<User> emailWrapper = new LambdaQueryWrapper<>();
            emailWrapper.eq(User::getEmail, addDTO.getEmail());
            User emailUser = userMapper.selectOne(emailWrapper);
            if (emailUser != null) {
                throw new BusinessException(ResultCode.PARAM_ERROR.getCode(), "邮箱已被使用");
            }
        }
        
        // 3. 检查手机号是否已被使用
        if (StringUtils.hasText(addDTO.getPhone())) {
            LambdaQueryWrapper<User> phoneWrapper = new LambdaQueryWrapper<>();
            phoneWrapper.eq(User::getPhone, addDTO.getPhone());
            User phoneUser = userMapper.selectOne(phoneWrapper);
            if (phoneUser != null) {
                throw new BusinessException(ResultCode.PARAM_ERROR.getCode(), "手机号已被使用");
            }
        }
        
        // 4. 创建用户对象
        User user = new User();
        user.setUsername(addDTO.getUsername());
        user.setPassword(BCrypt.hashpw(addDTO.getPassword()));
        user.setNickname(StringUtils.hasText(addDTO.getNickname()) ? 
                addDTO.getNickname() : addDTO.getUsername());
        user.setEmail(addDTO.getEmail());
        user.setPhone(addDTO.getPhone());
        user.setStatus(addDTO.getStatus() != null ? addDTO.getStatus() : 1);
        
        // 5. 保存到数据库
        int result = userMapper.insert(user);
        if (result <= 0) {
            throw new BusinessException("添加用户失败");
        }
        
        // 6. 分配角色
        if (addDTO.getRoleIds() != null && !addDTO.getRoleIds().isEmpty()) {
            roleService.assignRolesToUser(user.getId(), addDTO.getRoleIds());
        }
        
        log.info("添加用户成功，用户名：{}", user.getUsername());
        return convertToUserVO(user);
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public UserVO updateUser(UserUpdateDTO updateDTO) {
        // 1. 检查用户是否存在
        User user = userMapper.selectById(updateDTO.getId());
        if (user == null) {
            throw new BusinessException(ResultCode.USER_NOT_EXIST);
        }
        
        // 2. 检查邮箱是否被其他用户使用
        if (StringUtils.hasText(updateDTO.getEmail())) {
            LambdaQueryWrapper<User> emailWrapper = new LambdaQueryWrapper<>();
            emailWrapper.eq(User::getEmail, updateDTO.getEmail());
            emailWrapper.ne(User::getId, updateDTO.getId());
            User emailUser = userMapper.selectOne(emailWrapper);
            if (emailUser != null) {
                throw new BusinessException(ResultCode.PARAM_ERROR.getCode(), "邮箱已被使用");
            }
            user.setEmail(updateDTO.getEmail());
        }
        
        // 3. 检查手机号是否被其他用户使用
        if (StringUtils.hasText(updateDTO.getPhone())) {
            LambdaQueryWrapper<User> phoneWrapper = new LambdaQueryWrapper<>();
            phoneWrapper.eq(User::getPhone, updateDTO.getPhone());
            phoneWrapper.ne(User::getId, updateDTO.getId());
            User phoneUser = userMapper.selectOne(phoneWrapper);
            if (phoneUser != null) {
                throw new BusinessException(ResultCode.PARAM_ERROR.getCode(), "手机号已被使用");
            }
            user.setPhone(updateDTO.getPhone());
        }
        
        // 4. 更新用户信息
        if (StringUtils.hasText(updateDTO.getNickname())) {
            user.setNickname(updateDTO.getNickname());
        }
        if (StringUtils.hasText(updateDTO.getAvatar())) {
            user.setAvatar(updateDTO.getAvatar());
        }
        if (updateDTO.getStatus() != null) {
            user.setStatus(updateDTO.getStatus());
        }
        
        int result = userMapper.updateById(user);
        if (result <= 0) {
            throw new BusinessException("更新用户失败");
        }
        
        // 5. 更新角色
        if (updateDTO.getRoleIds() != null) {
            roleService.assignRolesToUser(user.getId(), updateDTO.getRoleIds());
        }
        
        log.info("更新用户成功，用户ID：{}", user.getId());
        return convertToUserVO(user);
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteUser(Long userId) {
        // 1. 检查用户是否存在
        User user = userMapper.selectById(userId);
        if (user == null) {
            throw new BusinessException(ResultCode.USER_NOT_EXIST);
        }
        
        // 2. 删除用户（逻辑删除）
        int result = userMapper.deleteById(userId);
        if (result <= 0) {
            throw new BusinessException("删除用户失败");
        }
        
        // 3. 删除用户角色关联
        LambdaQueryWrapper<com.fish.model.entity.UserRole> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(com.fish.model.entity.UserRole::getUserId, userId);
        userRoleMapper.delete(wrapper);
        
        log.info("删除用户成功，用户ID：{}", userId);
    }
    
    /**
     * 将User实体转换为UserVO
     */
    private UserVO convertToUserVO(User user) {
        UserVO userVO = new UserVO();
        BeanUtil.copyProperties(user, userVO);
        // 确保avatar字段不会导致序列化问题
        if (userVO.getAvatar() == null || userVO.getAvatar().isEmpty()) {
            userVO.setAvatar(null);
        }
        // 不返回密码等敏感信息
        log.debug("转换UserVO - ID: {}, username: {}, avatar: {}", 
                userVO.getId(), userVO.getUsername(), userVO.getAvatar());
        return userVO;
    }
    
    @Override
    public List<UserVO> searchUsers(String keyword) {
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        wrapper.and(w -> w.like(User::getUsername, keyword)
                .or()
                .like(User::getNickname, keyword));
        wrapper.eq(User::getStatus, 1); // 只搜索状态正常的用户
        wrapper.last("LIMIT 20"); // 限制返回数量
        
        List<User> users = userMapper.selectList(wrapper);
        return users.stream()
                .map(this::convertToUserVO)
                .collect(Collectors.toList());
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public LoginVO registerByEmail(com.fish.model.dto.EmailRegisterDTO registerDTO) {
        log.info("开始邮箱注册，邮箱：{}，验证码：{}", registerDTO.getEmail(), registerDTO.getCode());
        
        // 1. 验证邮箱验证码
        com.fish.common.service.VerificationCodeService codeService = 
            applicationContext.getBean(com.fish.common.service.VerificationCodeService.class);
        if (!codeService.verifyEmailCode(registerDTO.getEmail(), registerDTO.getCode())) {
            log.error("邮箱验证码验证失败，邮箱：{}", registerDTO.getEmail());
            throw new BusinessException("验证码错误或已过期");
        }
        
        log.info("验证码验证成功，检查邮箱是否已注册");
        
        // 2. 检查邮箱是否已被注册
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(User::getEmail, registerDTO.getEmail());
        if (userMapper.selectCount(wrapper) > 0) {
            log.error("邮箱已被注册，邮箱：{}", registerDTO.getEmail());
            throw new BusinessException("该邮箱已被注册");
        }
        
        // 3. 生成用户名（使用邮箱前缀）
        String username = registerDTO.getEmail().split("@")[0] + "_" + System.currentTimeMillis();
        log.info("生成用户名：{}", username);
        
        // 4. 创建用户
        User user = new User();
        user.setUsername(username);
        user.setEmail(registerDTO.getEmail());
        user.setPassword(BCrypt.hashpw(registerDTO.getPassword()));
        user.setNickname(StringUtils.hasText(registerDTO.getNickname()) ? 
                registerDTO.getNickname() : username);
        user.setStatus(1);
        
        userMapper.insert(user);
        log.info("用户创建成功，用户ID：{}", user.getId());
        
        // 5. 分配默认角色（普通用户）
        try {
            // 查询普通用户角色（role_key = 'user'）
            LambdaQueryWrapper<com.fish.model.entity.Role> roleWrapper = new LambdaQueryWrapper<>();
            roleWrapper.eq(com.fish.model.entity.Role::getRoleKey, "user");
            com.fish.model.entity.Role userRole = roleMapper.selectOne(roleWrapper);
            
            if (userRole != null) {
                roleService.assignRolesToUser(user.getId(), List.of(userRole.getId()));
                log.info("为新用户分配默认角色成功");
            } else {
                log.warn("未找到普通用户角色（role_key='user'），无法自动分配角色");
            }
        } catch (Exception e) {
            log.error("为新用户分配角色失败：", e);
        }
        
        // 6. 生成Token并返回
        String accessToken = JwtUtil.generateAccessToken(user.getId(), user.getUsername());
        String refreshToken = JwtUtil.generateRefreshToken(user.getId(), user.getUsername());
        
        // 保存RefreshToken
        tokenService.saveRefreshToken(user.getId(), refreshToken);
        
        log.info("邮箱注册成功，邮箱：{}，用户ID：{}", registerDTO.getEmail(), user.getId());
        
        return LoginVO.builder()
                .accessToken(accessToken)
                .refreshToken(refreshToken)
                .userInfo(convertToUserVO(user))
                .build();
    }
    
    @Override
    public LoginVO loginByEmail(com.fish.model.dto.EmailLoginDTO loginDTO) {
        log.info("开始邮箱验证码登录，邮箱：{}，验证码：{}", loginDTO.getEmail(), loginDTO.getCode());
        
        // 1. 验证邮箱验证码
        com.fish.common.service.VerificationCodeService codeService = 
            applicationContext.getBean(com.fish.common.service.VerificationCodeService.class);
        if (!codeService.verifyEmailCode(loginDTO.getEmail(), loginDTO.getCode())) {
            log.error("邮箱验证码验证失败，邮箱：{}", loginDTO.getEmail());
            throw new BusinessException("验证码错误或已过期");
        }
        
        log.info("验证码验证成功，开始查询用户");
        
        // 2. 查询用户
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(User::getEmail, loginDTO.getEmail());
        User user = userMapper.selectOne(wrapper);
        
        if (user == null) {
            log.error("用户不存在，邮箱：{}", loginDTO.getEmail());
            throw new BusinessException(ResultCode.USER_NOT_EXIST);
        }
        
        if (user.getStatus() == 0) {
            log.error("用户已被禁用，邮箱：{}", loginDTO.getEmail());
            throw new BusinessException(ResultCode.USER_DISABLED);
        }
        
        // 3. 生成Token
        String accessToken = JwtUtil.generateAccessToken(user.getId(), user.getUsername());
        String refreshToken = JwtUtil.generateRefreshToken(user.getId(), user.getUsername());
        
        // 保存RefreshToken
        tokenService.saveRefreshToken(user.getId(), refreshToken);
        
        log.info("邮箱验证码登录成功，邮箱：{}，用户ID：{}", loginDTO.getEmail(), user.getId());
        
        return LoginVO.builder()
                .accessToken(accessToken)
                .refreshToken(refreshToken)
                .userInfo(convertToUserVO(user))
                .build();
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateEmail(com.fish.model.dto.UpdateEmailDTO updateDTO) {
        // 1. 验证邮箱验证码
        com.fish.common.service.VerificationCodeService codeService = 
            applicationContext.getBean(com.fish.common.service.VerificationCodeService.class);
        if (!codeService.verifyEmailCode(updateDTO.getNewEmail(), updateDTO.getCode())) {
            throw new BusinessException("验证码错误或已过期");
        }
        
        // 2. 检查用户是否存在
        User user = userMapper.selectById(updateDTO.getUserId());
        if (user == null) {
            throw new BusinessException(ResultCode.USER_NOT_EXIST);
        }
        
        // 3. 检查新邮箱是否已被使用
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(User::getEmail, updateDTO.getNewEmail());
        wrapper.ne(User::getId, updateDTO.getUserId());
        if (userMapper.selectCount(wrapper) > 0) {
            throw new BusinessException("该邮箱已被使用");
        }
        
        // 4. 更新邮箱
        user.setEmail(updateDTO.getNewEmail());
        userMapper.updateById(user);
        
        log.info("更新邮箱成功，用户ID：{}，新邮箱：{}", updateDTO.getUserId(), updateDTO.getNewEmail());
    }
    
    @Override
    public boolean checkEmailExists(String email) {
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(User::getEmail, email);
        return userMapper.selectCount(wrapper) > 0;
    }

    @Override
    public void exportUserList(HttpServletResponse response, String username) {
        log.info("开始导出用户列表，筛选条件 username: {}", username);

        // 1. 查询用户列表
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        if (StringUtils.hasText(username)) {
            wrapper.like(User::getUsername, username);
        }
        List<User> userList = userMapper.selectList(wrapper);

        // 2. 转换为导出DTO
        List<UserExportDTO> exportList = userList.stream().map(user -> {
            UserExportDTO exportDTO = new UserExportDTO();
            exportDTO.setId(user.getId());
            exportDTO.setUsername(user.getUsername());
            exportDTO.setNickname(user.getNickname());
            exportDTO.setEmail(user.getEmail());
            exportDTO.setPhone(user.getPhone());
            exportDTO.setStatusName(user.getStatus() == 1 ? "正常" : "禁用");
            exportDTO.setCreateTime(user.getCreateTime());
            exportDTO.setUpdateTime(user.getUpdateTime());

            // 查询用户角色
            List<Role> roles = roleService.getRolesByUserId(user.getId());
            String roleNames = roles.stream()
                    .map(Role::getRoleName)
                    .collect(Collectors.joining(", "));
            exportDTO.setRoleNames(roleNames);

            return exportDTO;
        }).collect(Collectors.toList());

        // 3. 导出Excel
        ExcelUtil.exportExcel(response, "用户列表", "用户数据", UserExportDTO.class, exportList);
        log.info("导出用户列表成功，共 {} 条数据", exportList.size());
    }

    @Override
    public void downloadTemplate(HttpServletResponse response) {
        log.info("开始下载用户导入模板");
        ExcelUtil.exportTemplate(response, "用户导入模板", "用户数据", UserImportDTO.class);
        log.info("下载用户导入模板成功");
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ImportResult<User> importUserData(MultipartFile file) {
        log.info("开始导入用户数据，文件名: {}", file.getOriginalFilename());

        // 创建最终返回的结果对象
        ImportResult<User> finalResult = new ImportResult<>();

        // 使用监听器读取Excel
        ExcelImportListener<UserImportDTO> listener = new ExcelImportListener<>((dataList, importResult) -> {
            // 批量处理数据
            for (int i = 0; i < dataList.size(); i++) {
                UserImportDTO importDTO = dataList.get(i);
                int rowIndex = finalResult.getTotalCount() + i + 2; // Excel行号（从2开始，因为有表头）

                try {
                    // 1. 数据校验
                    String validationError = validateImportData(importDTO);
                    if (validationError != null) {
                        finalResult.addFailure(rowIndex, validationError);
                        continue;
                    }

                    // 2. 检查用户名是否已存在
                    LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
                    wrapper.eq(User::getUsername, importDTO.getUsername());
                    if (userMapper.selectCount(wrapper) > 0) {
                        finalResult.addFailure(rowIndex, "用户名已存在: " + importDTO.getUsername());
                        continue;
                    }

                    // 3. 检查邮箱是否已存在（如果有）
                    if (StringUtils.hasText(importDTO.getEmail())) {
                        LambdaQueryWrapper<User> emailWrapper = new LambdaQueryWrapper<>();
                        emailWrapper.eq(User::getEmail, importDTO.getEmail());
                        if (userMapper.selectCount(emailWrapper) > 0) {
                            finalResult.addFailure(rowIndex, "邮箱已存在: " + importDTO.getEmail());
                            continue;
                        }
                    }

                    // 4. 检查手机号是否已存在（如果有）
                    if (StringUtils.hasText(importDTO.getPhone())) {
                        LambdaQueryWrapper<User> phoneWrapper = new LambdaQueryWrapper<>();
                        phoneWrapper.eq(User::getPhone, importDTO.getPhone());
                        if (userMapper.selectCount(phoneWrapper) > 0) {
                            finalResult.addFailure(rowIndex, "手机号已存在: " + importDTO.getPhone());
                            continue;
                        }
                    }

                    // 5. 创建用户
                    User user = new User();
                    user.setUsername(importDTO.getUsername());
                    user.setNickname(importDTO.getNickname());
                    user.setEmail(importDTO.getEmail());
                    user.setPhone(importDTO.getPhone());
                    user.setStatus(importDTO.getStatus() != null ? importDTO.getStatus() : 1);
                    // 设置默认密码（123456）
                    user.setPassword(BCrypt.hashpw("123456"));
                    
                    userMapper.insert(user);

                    // 6. 分配默认角色（普通用户角色，role_id = 2）
                    UserRole userRole = new UserRole();
                    userRole.setUserId(user.getId());
                    userRole.setRoleId(2L); // 普通用户角色
                    userRoleMapper.insert(userRole);

                    finalResult.addSuccess(user);
                    log.info("导入用户成功: {}", user.getUsername());

                } catch (Exception e) {
                    log.error("导入用户失败，行号: {}, 数据: {}", rowIndex, importDTO, e);
                    finalResult.addFailure(rowIndex, "系统错误: " + e.getMessage());
                }
            }
        });

        // 读取Excel文件
        ExcelUtil.importExcelWithListener(file, UserImportDTO.class, listener);

        log.info("用户数据导入完成，总数: {}, 成功: {}, 失败: {}",
                finalResult.getTotalCount(), finalResult.getSuccessCount(), finalResult.getFailureCount());

        return finalResult;
    }

    /**
     * 校验导入数据
     */
    private String validateImportData(UserImportDTO importDTO) {
        if (!StringUtils.hasText(importDTO.getUsername())) {
            return "用户名不能为空";
        }
        if (!StringUtils.hasText(importDTO.getNickname())) {
            return "昵称不能为空";
        }
        if (importDTO.getUsername().length() < 3 || importDTO.getUsername().length() > 20) {
            return "用户名长度必须在3-20个字符之间";
        }
        if (StringUtils.hasText(importDTO.getEmail())) {
            if (!importDTO.getEmail().matches("^[A-Za-z0-9+_.-]+@[A-Za-z0-9.-]+$")) {
                return "邮箱格式不正确";
            }
        }
        if (StringUtils.hasText(importDTO.getPhone())) {
            if (!importDTO.getPhone().matches("^1[3-9]\\d{9}$")) {
                return "手机号格式不正确";
            }
        }
        if (importDTO.getStatus() != null && importDTO.getStatus() != 0 && importDTO.getStatus() != 1) {
            return "状态值只能是0或1";
        }
        return null;
    }
}